#include <iostream>
#include <vector>
#include "../include/ppread.h"
#include "../include/ppcustomermovie.h"
#include "boost/filesystem.hpp"
#include "../include/kNN.h"
#include "../include/print2file.h"
#ifdef USE_MPI
    #include <mpi.h>
    #include <fstream>
#endif
#include <cstdlib>
using namespace std;
namespace fs = boost::filesystem;

vector<short> readMovies(string fileName){
    ifstream in_movies_file(fileName.c_str());

    if(!in_movies_file.is_open()){
        cout<<"Sorry! file did not open"<<endl;
        in_movies_file.close();
        exit(1);
    }

    vector<short> vecMovies;
    while(!in_movies_file.eof()){
        string str;
        in_movies_file>>str;
        //cout<<str<<endl;
	vecMovies.push_back((short)atoi(str.c_str()));
    }

    return vecMovies;
}

int main(int argc, char* argv[])
{
    //cout << "Hello world!" << endl;
    if(argc != 3){
        cout<<"Error: The command line parameters are wrong.\n Usage: ./preprocess <directory name> K .\n";
        exit(1);
    }

    string strDirName = argv[1];
    string fileName = argv[3];
    int K = atoi(argv[2]);
    
#ifdef USE_MPI
    int numprocs, rank, namelen;
    MPI_Init(&argc, &argv);
    MPI_Comm_size(MPI_COMM_WORLD, &numprocs);
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
#endif

#ifdef USE_MPI
    char buff[100];
    sprintf(buff, "%d",rank);
    string strOpFileName = buff + string("_out.txt");
    kNN knn(strDirName, strOpFileName);
    vector<short> vecTestMovies;
    vector<short> vecTestMovies = readMovies(fileName);
    knn.kFoldXValidation(25, vecTestMovies, K, numprocs,rank);
    knn.printPrediction();
    
    cout<<"Done processing on processor #:"<<rank<<endl;
    MPI_Barrier( MPI_COMM_WORLD);
    MPI_Finalize();
#else
    //knn.findNearest(-1, -1, K);
    string strOpFileName("common_out.txt");
    //print2file outfile(strOpFileName);
    kNN knn(strDirName, strOpFileName);
    vector<short> vecTestMovies = readMovies(fileName);
    knn.kFoldXValidation(25, vecTestMovies, K, 1,0);
    knn.printPrediction();
#endif
    
    return 0;
}
